﻿#pragma once

#include "../../../http/http_base.hh"
#include "../lua_export_class.h"

#include "../../box_std_allocator.hh"

namespace kratos {
namespace service {
class ServiceBox;
}
} // namespace kratos

namespace kratos {
namespace http {
class HttpBaseImpl;
} // namespace http
} // namespace kratos

namespace kratos {
namespace lua {

namespace LuaUtil {
class LuaState;
}

class LuaServiceImpl;

/**
 * @brief HTTP类lua导出包装
 */
class LuaHttp : public LuaExportClass {
  kratos::service::ServiceBox *box_{nullptr}; ///< 服务容器
  lua_State *L_{nullptr};                     ///< lua虚拟机
  kratos::unique_pool_ptr<kratos::http::HttpBaseImpl> http_ptr_; ///< HTTP实例
  LuaServiceImpl *service_{nullptr}; ///< 服务容器
  int lua_reg_key_{LUA_NOREF};       ///< Lua注册表key
  int callback_index_{1};            ///< 回调函数key
  using FunctionIndexList = kratos::service::PoolList<int>;
  FunctionIndexList listener_function_list_;  ///< 监听器回调函数key
  FunctionIndexList connector_function_list_; ///< 连接器回调函数key
  using ResponseMap =
      kratos::service::PoolUnorederedMap<int, kratos::http::HttpCallPtr>;
  ResponseMap response_map_;           ///< {key, 未处理完成的response}
  kratos::http::HeaderMap header_map_; ///< HTTP header
  bool started_{false};                ///< 是否已经启动http服务

public:
  /**
   * @brief 构造
   * @param box 服务容器
   * @param L 虚拟机
   * @param service lua服务
   */
  LuaHttp(kratos::service::ServiceBox *box, lua_State *L,
          LuaServiceImpl *service);
  /**
   * 析构
   */
  virtual ~LuaHttp();
  virtual auto do_register() -> bool override;
  virtual auto update(std::time_t ms) -> void override;
  virtual auto do_cleanup() -> void override;

private:
  /**
   * @brief HTTP server处理函数
   * @param request HTTP请求
   * @param response HTTP响应
   * @param user_data 用户数据
   * @return true表示处理完成, false表示处理进行中
   */
  auto http_request_handler(kratos::http::HttpCallPtr request,
                            kratos::http::HttpCallPtr response,
                            std::uint64_t user_data) -> bool;
  /**
   * @brief HTTP client处理函数
   * @param response HTTP响应
   * @param user_data 用户数据
   * @return
   */
  auto http_response_handler(kratos::http::HttpCallPtr response,
                             std::uint64_t user_data) -> void;
  /**
   * @brief HTTP client协程退出事件处理函数
   * @param user_data 用户数据
   * @param thread 协程
   * @param normal_terminated 是否是正常退出
   * @return
   */
  auto thread_exit_event_handler_client(std::uint64_t user_data,
                                        LuaThread *thread,
                                        bool normal_terminated) -> void;
  /**
   * @brief HTTP server协程退出事件处理函数
   * @param user_data 用户数据
   * @param thread 协程
   * @param normal_terminated 是否是正常退出
   * @return
   */
  auto thread_exit_event_handler_server(std::uint64_t user_data,
                                        LuaThread *thread,
                                        bool normal_terminated) -> void;
  /**
   * @brief 产生一个新的索引
   * @return 索引
   */
  auto new_index() -> int;
  /**
   * @brief 获取HTTP header
   * @param l 协程
   * @return HTTP header表
   */
  auto get_header(lua_State *l) -> const kratos::http::HeaderMap &;
  /**
   * @brief 添加HTTP client lua回调函数
   * @param lua_state 协程
   * @param index 索引
   * @return true或false
   */
  auto add_lua_callback_client(LuaUtil::LuaState& lua_state, int index) -> bool;
  /**
   * @brief 删除HTTP client lua回调函数
   * @param lua_state 协程
   * @param index  索引
   * @return true或false
   */
  auto remove_lua_callback_client(LuaUtil::LuaState& lua_state, int index) -> bool;
  /**
   * @brief 添加HTTP server lua回调函数
   * @param lua_state 协程
   * @param index 索引
   * @return true或false
   */
  auto add_lua_callback_server(LuaUtil::LuaState& lua_state, int index) -> bool;

private:
  static LuaHttp *get_http(lua_State *l);
  static bool check_wait_response_param(const LuaUtil::LuaState &lua_state);

private:
  static int lua_wait_request(lua_State *l);
  static int lua_wait_response(lua_State *l);
};

} // namespace lua
} // namespace kratos
